/*
 * singleNumber_Converter.cpp
 *
 *  Created on: 09.06.2014
 *      Author: Zejing Li
 */

#include <iostream>

#include "converter/roman_numeral_converter.h"
#include "util/util.h"

using namespace std;

string a::RomanNumeralConverter::convert(int arabic) {
	int i = 0;
	string result = "";
	while (arabic > 0) {
		int digit = arabic % 10;
		result = convertDigit(digit, i) + result;
		arabic /= 10;
		i++;
	}
	return result;
}

string a::RomanNumeralConverter::convertDigit(int digit, int position) {
	string oneNumberRoman = romanParsingList[digit];
	vector<string> romanAlphabetForDigit = obtainRomanAlphabetForDigit(
			position);

	for (unsigned int i = 0; i < romanAlphabetForDigit.size(); i++) {
		oneNumberRoman = Util::replaceAll(oneNumberRoman, parsingAssistList[i],
				romanAlphabetForDigit[i]);
	}
	return oneNumberRoman;
}

vector<string> a::RomanNumeralConverter::obtainRomanAlphabetForDigit(
		int position) {
	int p = position % 3;
	int q = position / 3;
	vector<string> romanAlphabetForDigit(3);

	for (unsigned int i = 0; i < romanAlphabetForDigit.size(); i++) {
		romanAlphabetForDigit[i] = romanAlphabetForDigitList[p].substr(i, 1);
	}

	// for a number larger than 1000, we use x* represent x times 1000, x**
	// represent x times 1000 times 1000 and so on;
	// because of the existence of "M" in the "romanTable"(namely:M=I times
	// 1000), we have to replace I* by M.
	if (q > 0) {
		for (int j = 1; j <= q; j++) {
			for (unsigned int i = 0; i < romanAlphabetForDigit.size(); i++) {
				romanAlphabetForDigit[i] += "*";
			}
		}
		// replace I* by M
		if ((romanAlphabetForDigit[0].compare(0, 1,
				romanAlphabetForDigitList[0].substr(0, 1)) == 0)) {
			romanAlphabetForDigit[0].replace(0, 2,
					romanAlphabetForDigitList[2].substr(2, 1));
		}
	}
	return romanAlphabetForDigit;
}

const std::vector<std::string> a::RomanNumeralConverter::romanParsingList = {
		"", "a", "aa", "aaa", "ab", "b", "ba", "baa", "baaa", "ac" };
const std::vector<std::string> a::RomanNumeralConverter::romanAlphabetForDigitList =
		{ "IVX", "XLC", "CDM" };
const std::vector<std::string> a::RomanNumeralConverter::parsingAssistList = {
		"a", "b", "c" };

